import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer # 以乳腺癌数据集为例
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.inspection import permutation_importance

#----------- 数据准备 -----------
# 加载内置数据集
data = load_breast_cancer() #特征数据，（数据条数，特征数）
X = pd.DataFrame(data.data, columns=data.feature_names)
y = pd.Series(data.target) #目标标签，（数据条数，），包含0，1两类
                        
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)

#----------- 训练随机森林模型 -----------
# 初始化模型，设置随机种子以确保结果可重现
# n_estimators是森林中树的数量，通常越多越好，但计算成本也越高
rf = RandomForestClassifier(n_estimators=100, random_state=42)

# 训练模型
rf.fit(X_train, y_train)

# 评估模型在测试集上的准确率
print(f"Model accuracy on test set: {rf.score(X_test, y_test):.4f}")

#----------- 特征重要性评估 -----------
# 获取特征重要性（MDI）
importances_mdi = rf.feature_importances_

# 创建一个DataFrame以便于排序和可视化
feature_names = X.columns
mdi_df = pd.DataFrame({'Feature': feature_names, 'Importance (MDI)': importances_mdi})  #字典的键名指定了columns
mdi_df = mdi_df.sort_values('Importance (MDI)', ascending=False)

# 打印最重要的10个特征
print(mdi_df.head(10))

# 获取基于排列的特征重要性（MDA）
# 计算排列重要性
perm_result = permutation_importance(rf, X_test, y_test, n_repeats=10, random_state=42, n_jobs=1) # n_repeats重复打乱次数，越高越稳定。njobs取-1可以并行计算，如果数据量大则开
# 整理结果
importances_perm = perm_result.importances_mean #获取平均重要性
perm_df = pd.DataFrame({'Feature': feature_names, 'Importance (Permutation)': importances_perm})
perm_df = perm_df.sort_values('Importance (Permutation)', ascending=False) #倒序排序

# 打印最重要的10个特征
print(perm_df.head(10))

#----------- 可视化结果 -----------
def plot_importance_df(df, title, method):
    """绘制特征重要性条形图的函数"""
    df = df.sort_values(method, ascending=True)
    plt.figure(figsize=(10, 8))
    plt.barh(df['Feature'][-15:], df[method][-15:]) # 显示最重要的15个特征
    plt.xlabel('Importance')
    plt.title(title)
    plt.tight_layout()
    plt.show()

# 绘制两种方法的结果
plot_importance_df(mdi_df, 'Feature Importance (MDI)', 'Importance (MDI)')
plot_importance_df(perm_df, 'Feature Importance (Permutation)', 'Importance (Permutation)')
